﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.Generic;
using Microsoft.Practices.Composite.Events;
using RiaCrm.DataAccessLayer;
using Acando.Dynamics.CRM.Silverlight.Library.Controls.FieldControls;
using Acando.Dynamics.CRM.Silverlight.Library.Interfaces;
using Acando.Dynamics.CRM.Silverlight.Library.CrmSdk;
using Acando.Dynamics.CRM.Silverlight.Library.Types;
using Acando.Dynamics.CRM.Silverlight.Library.MetaSdk;
using System.Xml.Linq;
using Acando.Dynamics.CRM.Silverlight.Library.Helper;
using RiaCrm.Infrastructure;
using Microsoft.Practices.Composite.Presentation.Commands;
using Acando.Dynamics.CRM.Silverlight.Library.Model;

namespace RiaCrm.EditRecord
{
    public class EditRecordViewModel : INotifyPropertyChanged, IRecordControl, IProviedMetaDataLayer
    {
        
        private Pair<EntityMetadata, XElement> _fromDefinition;
        private static Dictionary<string, Pair<EntityMetadata, XElement>> FormCache =
                                              new Dictionary<string, Pair<EntityMetadata, XElement>>();
        public Boolean IsReadOnly { get; set; }
        public IMetaDataLayer Metadatalayer { get; set; }
        public String Organame { get; set; }
        private BusinessEntity _newItem;
        private BusinessEntity _editItem;
        private IDataModel _dataModel;
        private IEventAggregator _eventAggregator;
        
        public Dictionary<string, CrmPicklistControl> RegisteredPicklists
        {
            get;
            private set;
        }


        public IDataModel DataModel
        {
            get
            {
                if(this._dataModel == null)
                    this._dataModel = new DynamicDataModel(((DynamicEntity)this.EditItem).Name, this.Organame);
                
                return this._dataModel;
            } 
        }
        public Boolean CurrentItemIsNew
        {
            get { return _newItem != null; }
        }
        public Boolean CurrentItemIsNotNull
        {
            get { return CurrentItem != null; }
        }
       
        public Pair<EntityMetadata, XElement> FormDefinition
        {
            get { return this._fromDefinition; }
            set 
            {
                this._fromDefinition = value;
                OnPropertyChanged("FormDefinition");
            }
        }

        public BusinessEntity CurrentItem
        {
            get { return _newItem != null ? _newItem : _editItem; }
        }

        public BusinessEntity EditItem
        {
            get { return _editItem; }
            set
            {
                _editItem = value;
                OnEntityChanges();
                OnPropertyChanged("Entity");
                OnPropertyChanged("CurrentItem");
                OnPropertyChanged("CurrentItemIsNew");
                OnPropertyChanged("CurrentItemIsNotNull");
            }
        }

        public BusinessEntity NewItem
        {
            get { return _newItem; }
            set
            {
                _newItem = value;

                OnPropertyChanged("CurrentItem");
                OnPropertyChanged("CurrentItemIsNew");
                OnPropertyChanged("CurrentItemIsNotNull");
            }
        }

        public BusinessEntity Entity
        {
            get { return this.CurrentItem; }
        }

        public ICommand newCommand { get; private set; }
        public ICommand cancelCommand { get; private set; }
        public ICommand saveCommand { get; private set; }

        /* Constructor */
        public EditRecordViewModel(IEventAggregator eventAggregator, InitParaOrgaName organame, IMetaDataLayer metadatalayer)
        {
            this.RegisteredPicklists = new Dictionary<string, CrmPicklistControl>();
            this.Organame = organame.Value;
            this.Metadatalayer = metadatalayer;
            this.newCommand = new DelegateCommand<string>(OnNewButtonClick);
            this.cancelCommand = new DelegateCommand<string>(OnCancelButtonClick);
            this.saveCommand = new DelegateCommand<string>(OnSaveButtonClick);

            this._eventAggregator = eventAggregator;
            this._eventAggregator.GetEvent<DynamicEntityGridSelecteIndexChanged>().Subscribe(OnDynEntityGridSelectionChanged);
            try
            {
                this._eventAggregator.GetEvent<StatedEntityChanged>().Subscribe(OnStatedEntityChanged);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void OnStatedEntityChanged(string newEntityTypename)
        {
            
            if (FormCache.ContainsKey(newEntityTypename))
            {
                this.FormDefinition = FormCache[newEntityTypename];
            }
            else
            {
                RetrieveFromXmlHelper helper = new RetrieveFromXmlHelper(this.Organame);
                helper.RetrieveFormXmlAsyn(newEntityTypename, this.Metadatalayer, this.RetrieveFromXmlCallback);
            }
        }

        private void OnSaveButtonClick(string dummy)
        {
            if (this.CurrentItemIsNew)
            {
                this.DataModel.Create(this.CurrentItem as BusinessEntity);
                this.EditItem = this.NewItem;
                this.NewItem = null;
                this._eventAggregator.GetEvent<DataSourceChanged>().Publish("EditRecordViewModel");
            }
            else
            {
                DataModel.Update(this.CurrentItem as BusinessEntity);
            }
        }

        private void OnCancelButtonClick(string dummy)
        {
            this.NewItem = null;
        }

        private void OnNewButtonClick(string dummy)
        {
            if (!this.CurrentItemIsNew)
            {
                if (this._dataModel == null)
                    this._dataModel = new DynamicDataModel(((DynamicEntity)this.EditItem).Name, this.Organame);

                this.NewItem = this._dataModel.NewItem();
            }
        }

        private void OnEntityChanges()
        {
            // hier view informieren das Panel angezeigt werden soll!

            if (this.EditItem != null)
            {
                string entitytypename;

                if (this.EditItem is DynamicEntity)
                    entitytypename = ((DynamicEntity)this.EditItem).Name;
                else
                    entitytypename = this.EditItem.GetType().Name; 

               
                if (FormCache.ContainsKey(entitytypename))
                {
                    this.FormDefinition = FormCache[entitytypename];
                }
                else
                {
                    RiaCrm.DataAccessLayer.RetrieveFromXmlHelper helper = new RiaCrm.DataAccessLayer.RetrieveFromXmlHelper(this.Organame);
                    helper.RetrieveFormXmlAsyn(entitytypename,this.Metadatalayer, this.RetrieveFromXmlCallback);
                }
            }
        }


        # region Callback functions

        private void RetrieveFromXmlCallback(Pair<EntityMetadata, string> result)
        {
            this.FormDefinition = new Pair<EntityMetadata, XElement> { Type1 = result.Type1,
                                                                       Type2 = XElement.Parse(result.Type2)};
        }

        # endregion

        public void OnDynEntityGridSelectionChanged(object selectedItem)
        {
            DynamicEntity item = selectedItem as DynamicEntity;

            if (item == null && selectedItem != null)
                throw new Exception("Recieved unkown Type."); 
            else
                this.EditItem = item;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
